# -*- coding:utf-8 -*-

import datetime
from flask import Flask, g, jsonify, current_app, request, session
from iHome.models import Area, Facility, User, House, HouseImage, Order
from . import api
from iHome.utils.response_code import RET
# 缓存引用的模块
from iHome import redis_store, db
# 引入缓存的过期时间
from iHome.constants import AREA_INFO_REDIS_EXPIRES, QINIU_DOMIN_PREFIX, HOUSE_DETAIL_REDIS_EXPIRE_SECOND, HOME_PAGE_MAX_HOUSES
from iHome.constants import HOME_PAGE_DATA_REDIS_EXPIRES, HOUSE_LIST_PAGE_CAPACITY
from iHome import constants
# 引入判断登录的装饰器
from iHome.utils.common import login_required
# 导入上传图片的方法
from iHome.utils.storage_image import storage_image


@api.route("/houses")
def search_house():
    # 先把所有的房屋查询出来
    """
     var params = {
        aid:areaId,
        sd:startDate,
        ed:endDate,
        sk:sortKey,
        p:next_page
    };
    :return:
    """
    args = request.args
    # 区域的id
    aid = args.get("aid", "")
    # 用户的入住时间
    start_date_str = args.get("sd", "")
    # 用户的离开时间
    end_date_str = args.get("ed", "")
    # new 最新上线　booking 入住最多　price-inc　价格 低-高　price-des　价格 高-低
    sk = args.get("sk", "new")
    p = args.get("p", 1)

    start_date = None
    end_date = None
    # 判断参数
    try:
        if start_date_str:
            start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d")
        if end_date_str:
            end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d")

        if start_date and end_date:
            assert start_date < end_date, Exception("开始时间不能大于结束是时间")
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数有误")

    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数有误")

    # TODO:从redis中读取房屋数据
    try:
        redis_key = "house_list_%s_%s_%s_%s" % (aid, start_date_str, end_date_str, sk)
        response_dict = redis_store.hget(redis_key, p)
        if response_dict:
            return jsonify(errno=RET.OK, errmsg="ok", data=eval(response_dict))
    except Exception as e:
        current_app.logger.error(e)

    # 先把所有的房屋数据查询出来并返回
    try:
        house_query = House.query
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

    # 过滤条件的列表
    filters = []
    if aid:
        #添加过滤条件
        filters.append(House.area_id == aid)
    # 定义的冲突订单
    conflict_order = None
    if start_date and end_date:
        conflict_order = Order.query.filter(Order.begin_date < end_date, Order.end_date > start_date).all()
        pass
    elif start_date:
        conflict_order = Order.query.filter(Order.end_date > start_date).all()
        pass
    elif end_date:
        conflict_order = Order.query.filter(Order.begin_date < end_date).all()
        pass

    # 有无冲突的订单
    if conflict_order:
        # 取到这些冲突的订单的房屋id
        conflict_order_ids = [order.house_id for order in conflict_order]
        # 不包含冲突订单的房屋id
        filters.append(House.id.notin_(conflict_order_ids))

    # 根据不同的排序方式去查询
    if sk == "booking":
        house_query = house_query.filter(*filters).order_by(House.order_count.desc())
    elif sk == "price-inc":
        house_query = house_query.filter(*filters).order_by(House.price.asc())
    elif sk == "price-des":
        house_query = house_query.filter(*filters).order_by(House.price.desc())
    else:
        house_query = house_query.filter(*filters).order_by(House.create_time.desc())

    # 获取当分页对象　第一个参数：第几页的数据　第二个参数：每一页有多少个　参数三：是否输出错误
    paginate = house_query.paginate(int(p), HOUSE_LIST_PAGE_CAPACITY, False)

    # 取到当前页对象
    houses = paginate.items
    # 记录总页数
    total_page = paginate.pages
    houses_dict = []
    for house in houses:
        houses_dict.append(house.to_basic_dict())

    response_dict = {"houses": houses_dict, "total_page": total_page}
    # TODO:保存房屋数据
    if p <= total_page:   # 当前页如果小于等于总页数
        try:
            redis_key = "house_list_%s_%s_%s_%s" % (aid, start_date_str, end_date_str, sk)
            # 获取到管道操作
            pipe = redis_store.pipeline()
            # 开启事物
            pipe.multi()
            # 设置数据
            pipe.hset(redis_key, p, response_dict)
            # 设置过期时间
            pipe.expire(constants.HOUSE_LIST_REDIS_EXPIRES)
            # 提交事物
            pipe.execute()
        except Exception as e:
            current_app.logger.error(e)
            # return jsonify(errno=RET.DBERR, errmsg="查询数据失败")
    return jsonify(errno=RET.OK, errmsg="ok", data=response_dict)


@api.route("/houses/index")
def get_houses_index():
    """首页推荐的房屋，以订单数量来排序（倒序）
    :return"""
    # 尝试从缓存中取数据
    try:
        houses_dict = redis_store.get("home_house_index")
        if houses_dict:
            return jsonify(errno=RET.OK, errmsg="ok", data=eval(houses_dict))
    except Exception as e:
        current_app.logger.error(e)

    # 查询房屋数据，以订单号倒叙排序，最前５个
    try:
        houses = House.query.order_by(House.order_count.desc()).limit(HOME_PAGE_MAX_HOUSES).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

    houses_dict = []
    if houses:
        for house in houses:
            houses_dict.append(house.to_basic_dict())

        # 去缓存数据
        try:
            redis_store.set("home_house_index", houses_dict, HOME_PAGE_DATA_REDIS_EXPIRES)
        except Exception as e:
            current_app.logger.error(e)
        return jsonify(errno=RET.OK, errmsg="ok", data=houses_dict)
    return jsonify(errno=RET.OK, errmsg="ok", data=houses_dict)


@api.route("/houses/<int:house_id>")
def get_house_detail(house_id):
    """１．通过house_id查询出房屋
    ２．将房屋模型的数据封装到字典中（取到当前用户的id，如果用户没有登录，值为-1表示未登录）
    ３．直接返回
    4.将房屋数据缓存到redis中
    """
    user_id = session.get("user_id")
    # 去读取缓存数据
    try:
        house_dict = redis_store.get("house_detail_%d" % house_id)
        if house_dict:
            return jsonify(errno=RET.OK, errmsg="OK", data={'user_id': user_id, "house": eval(house_dict)})
    except Exception as e:
        current_app.logger.error(e)

    # 通过house_id查询出房屋　
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")

    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    # 生成要返回的信息

    house_dict = house.to_full_dict()

    # 去缓存
    try:
        redis_store.set("house_detail_%d" % house_id , house_dict, HOUSE_DETAIL_REDIS_EXPIRE_SECOND)
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errno=RET.OK, errmsg="OK", data={"user_id": user_id, "house": house_dict})


@api.route("/houses/<int:house_id>/images",methods=['POST'])
def upload_house_image(house_id):
    """1.取到参数，house_id要长春的图片
    ２．查询对应id的房屋
    3.在上传图片
    ４．保存图片，判断房屋的首页是否有值，如果没有，设置
    """
    try:
        house_image_file = request.files.get("house_image").read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 2.查询是否有指定房屋
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询房屋信息失败")
    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋信息不存在")

    # 3.在上传图片
    try:
        url = storage_image(house_image_file)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg="上传图片失败")

    # 4.初始化模型
    house_image = HouseImage()
    house_image.house_id = house_id
    house_image.url = url

    try:
        # 设置房屋的头图
        if not house.index_image_url:
            house.index_image_url = url

        db.session.add(house_image)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存图片数据失败")
    return jsonify(errno=RET.OK, errmsg="OK", data={"url": QINIU_DOMIN_PREFIX + url})


@api.route("/houses", methods=['POST'])
@login_required
def save_new_house():
    """1.获取上传的参数
    2.判断是否为空，校验参数
    3.初始化一个house的对象
    4.进行数据保存
    5.返回结果
    前端发送过来的json数据
    {
        "title":"",
        "price":"",
        "area_id":"1",
        "address":"",
        "room_count":"",
        "acreage":"",
        "unit":"",
        "capacity":"",
        "beds":"",
        "deposit":"",
        "min_days":"",
        "max_days":"",
        "facility":["7","8"]
    }"""
    # 1.获取上传的参数
    user_id = g.user_id
    json_dict = request.json
    title = json_dict.get('title')
    price = json_dict.get('price')
    address = json_dict.get('address')
    area_id = json_dict.get('area_id')
    room_count = json_dict.get('room_count')
    acreage = json_dict.get('acreage')
    unit = json_dict.get('unit')
    capacity = json_dict.get('capacity')
    beds = json_dict.get('beds')
    deposit = json_dict.get('deposit')
    min_days = json_dict.get('min_days')
    max_days = json_dict.get('max_days')

    # 2.判断是否为空，校验参数
    if not all([title, price, address, area_id, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')

    #判断传入的金额是否时数字，２．将其转成以分为单位
    try:
        price = int(float(price)*100)
        deposit = int(float(deposit) * 100)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数缺失")
    # 3.初始化一个house的对象
    house = House()
    house.user_id = user_id
    house.area_id = area_id
    house.title = title
    house.price = price
    house.address = address
    house.room_count = room_count
    house.acreage = acreage
    house.unit = unit
    house.capacity = capacity
    house.beds = beds
    house.deposit = deposit
    house.min_days = min_days
    house.max_days = max_days

    # 设置房屋设施
    facilities = json_dict.get("facility")

    if facilities:
        # 查询指定列表中对应的模型并设置设施信息
        house.facilities = Facility.query.filter(Facility.id.in_(facilities)).all()

    # 保存房屋数据
    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="添加数据失败")
    return jsonify(errno=RET.OK, errmsg="OK", data={'house_id': house.id})


@api.route("/areas")
def get_areas():
    """获取城区信息"""
    # 0.先从redis中取
    try:
        areas = redis_store.get("areas")
        # print areas
        if areas:
            return jsonify(errno=RET.OK, errmsg="OK", data={'areas': eval(areas)})

    except Exception as e:
        current_app.logger.error(e)

    # 1.获取所有的城区信息
    areas = Area.query.all()
    # 2.因为areas是一个对象列表，不能直接返回，需要将其转换成字典的列表
    areas_array = []
    for area in areas:
        areas_array.append(area.to_dict())
    # 3.将数据缓存到redis中
    try:
        redis_store.set("areas", areas_array, AREA_INFO_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    # 4.数据返回
    return jsonify(errno=RET.OK, errmsg="OK", data={"areas": areas_array})
